import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by sToa on 2014/11/18.
 */
public class XmlParser
{
    public static Map<String, Object> dataMap = null;
    public static Map<String, Object> regexMap = null;
    public static void parse(String xmlStr, String fileName, int fileIndex)
    {
        try {
            if(!StringUtils.isEmpty(xmlStr))
            {
                DocumentBuilderFactory docbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder docb = docbf.newDocumentBuilder();
//                StringReader sr = new StringReader(xmlStr);
//                InputSource is = new InputSource(sr);
                Document doc = docb.parse(new File("D:/WorkSpace-IDE/parser/src/main/resources/xml/" + fileName));
                Document regDoc = docb.parse(new File("D:/WorkSpace-IDE/parser/src/main/resources/xml/GeneralPatternDefinitions.xml"));
                XPathFactory xPathFactory = XPathFactory.newInstance();
                XPath xPath = xPathFactory.newXPath();

                dataMap = new HashMap<String, Object>();

                XPathExpression xpExpr = xPath.compile("/eventParser/deviceType/*");
                Object result = xpExpr.evaluate(doc, XPathConstants.NODESET);
                NodeList nodes = (NodeList)result;
//                NodeList chNodes = node.getChildNodes();
//                System.out.println(nodes.getLength());
                for(int i=0; i<nodes.getLength(); i++)
                {
                    dataMap.put(nodes.item(i).getNodeName(), nodes.item(i).getTextContent());
                }

                xpExpr = xPath.compile("/eventParser/appType/*");
                result = xpExpr.evaluate(doc, XPathConstants.NODESET);
                nodes = (NodeList)result;
                for(int i=0; i<nodes.getLength(); i++)
                {
                    dataMap.put(nodes.item(i).getNodeName(), nodes.item(i).getTextContent());
                }

                xpExpr = xPath.compile("//pattern");
                result = xpExpr.evaluate(regDoc, XPathConstants.NODESET);
                nodes = (NodeList)result;
                if(nodes.getLength() > 0)
                {
                    regexMap = new HashMap<String, Object>();
                }
                for(int i=0; i<nodes.getLength(); i++)
                {
                    String key = nodes.item(i).getAttributes().getNamedItem("name").getNodeValue();
                    if(regexMap.isEmpty() || !regexMap.containsKey(key))
                    {
                        regexMap.put(key, nodes.item(i).getTextContent());
                    } else
                    {
                        regexMap.put(key, regexMap.get(key) + nodes.item(i).getTextContent());
                    }
//                    System.out.println("Pattern: "+key + " " + nodes.item(i).getTextContent());
                }

                xpExpr = xPath.compile("/eventParser/patternDefinitions/*");
                result = xpExpr.evaluate(doc, XPathConstants.NODESET);
                nodes = (NodeList)result;

                for(int i=0; i<nodes.getLength(); i++)
                {
                    String key = nodes.item(i).getAttributes().getNamedItem("name").getNodeValue();
                    if(regexMap.isEmpty() || !regexMap.containsKey(key))
                    {
                        regexMap.put(key, nodes.item(i).getTextContent());
                    } else
                    {
                        regexMap.put(key, regexMap.get(key) + nodes.item(i).getTextContent());
                    }
//                    System.out.println(nodes.item(i).getNodeName() + " " + nodes.item(i).getAttributes().getNamedItem("name").getNodeValue() + " " + nodes.item(i).getTextContent());
                }
//                System.out.println(regexMap);
                xpExpr = xPath.compile("/eventParser/eventFormatRecognizer");
                result = xpExpr.evaluate(doc, XPathConstants.NODE);
                Node node = (Node)result;
                if(node != null)
                {
                    String eventRecog = str2Regex(node.getTextContent(), regexMap).trim();

                    xpExpr = xPath.compile("//testEvent");
                    result = xpExpr.evaluate(doc, XPathConstants.NODESET);
                    nodes = (NodeList)result;
                    for(int i=0; i<nodes.getLength(); i++)
                    {
//                    System.out.println(nodes.item(i).getNodeName() + " " + nodes.item(i).getTextContent());
                        if(StringUtils.isEmpty(nodes.item(i).getTextContent()))
                        {
                            boolean b = isRecognize(nodes.item(i).getTextContent(), eventRecog);
                            if(!b)
                            {
                                System.out.println(fileIndex + " " + fileName + " " + b);
                            }
                        }
                    }
                }

                xpExpr = xPath.compile("/eventParser/parsingInstructions/*");
                result = xpExpr.evaluate(doc, XPathConstants.NODESET);
                nodes = (NodeList)result;
                for(int i=0; i<nodes.getLength(); i++)
                {
                    System.out.println(nodes.item(i).getNodeName() + " " + nodes.item(i).getTextContent());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean isRecognize(String testEvent, String regex)
    {
        Pattern p = Pattern.compile(regex);
        boolean b = false;
        Matcher m = p.matcher(testEvent);
//        b = m.matches();
//        m.reset();
//        System.out.println(m.toMatchResult());
//        System.out.println(m.groupCount());
        if(!b)
        {
            b = m.find();
//            while (b = m.find())
//            {
//                System.out.println(m.group());
//            }
        }
        return b;
    }

    public static String str2Regex(String oldStr, Map<String, Object> regexMap)
    {
//        System.out.println(oldStr);
        if(!regexMap.isEmpty())
        {
            for(Iterator<Map.Entry<String, Object>> iter = regexMap.entrySet().iterator(); iter.hasNext();)
            {
                Map.Entry<String, Object> entry = iter.next();
                oldStr = oldStr.replace("<:"+entry.getKey()+">", entry.getValue()+"");
            }
        }
//        System.out.println(oldStr);
        return oldStr;
    }

    public static void main(String[] args) throws Exception
    {
        File dir = new File("D:/WorkSpace-IDE/parser/src/main/resources/xml/");
        File[] files = dir.listFiles();
        for(File f: files)
        {
//            System.out.println(f.getName());
            if(!f.getName().contains(".xml"))
            {
                continue;
            }
            parse("", f.getName(), ArrayUtils.indexOf(files, f));
        }
//        String re = "\\d{2,4}-\\d{1,2}-\\d{1,2}\\s+\\d{1,2}:\\d{1,2}:\\d{1,2},\\d+\\s+\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\s+[^ ]*\\s+";
//        String da = "2012-05-30 16:07:55,484  192.168.1.68 AO361 0 1 0 protocol=RADIUS,username=test1,login_status=REJECT,request_timestamp=2012-05-30 16:06:23-07,connection_dest_ip_address=192.168.1.68,connection_nad_ip_address=192.168.26.7,";
//        System.out.println(isRecognize(da, re));
//        String stmt = "xx[new Date('08/24/2013'), 9.39],[new Date('09/25/2014'), 19.139],";
//        String regex = "\\[(.*?)\\],";
//        Pattern p = Pattern.compile(regex);
//        Matcher m = p.matcher(stmt);
//        System.out.println(m.matches() + " " + m.groupCount());
//        while(m.find()){
//            System.out.println(m.group(0));
//            System.out.println(m.group(1));
//        }

//        String regex = "java";
//        String s = "head java is very good java tail";
//        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
//        Matcher m = p.matcher(s);
//        StringBuffer sb = new StringBuffer();
//        while (m.find()) {
//            String t = m.group(0);
//            // replace
//            m.appendReplacement(sb, "C#");
//            System.out.println("end:" + m.end());
//            System.out.println("start:" + m.start());
//            System.out.println("sb:" + sb);
//            System.out.println("t:" + t);
//        }
//        // tail
//        m.appendTail(sb);
//        System.out.println(sb);

    }

}
